﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Security;

namespace DevelopTool.Common
{
    public class WindowsHelper
    {
        #region 任务栏闪烁

        [DllImport("User32.dll",CharSet = CharSet.Unicode,EntryPoint = "FlashWindowEx")]
        private static extern void FlashWindowEx(ref FLASHWINFO pwfi);
        public struct FLASHWINFO
        {
            public uint cbSize;//该结构的字节大小
            public IntPtr hwnd;//要闪烁的窗口的句柄，该窗口可以是打开的或最小化的
            public uint dwFlags;//闪烁的状态
            public uint uCount;//闪烁窗口的次数
            public uint dwTimeout;//窗口闪烁的频度，毫秒为单位；若该值为0，则为默认图标的闪烁频度
        }

        public const uint FLASHW_TRAY = 2;//0x00000002 闪烁窗口的任务栏按钮
        public const uint FLASHW_TIMERNOFG = 12;//0x0000000C 不停地闪烁，直到窗口前端显示
        public const uint FLASHW_ALL = 0x00000003;//0x00000003 同时闪烁窗口标题和窗口的任务栏按钮，相当于FALSHW_CAPTION | FLASHW_TRAY

        /// <summary>
        /// 任务栏图标闪烁
        /// </summary>
        /// <param name="hwnd">要闪烁的窗口的句柄，该窗口可以是打开的或最小化的</param>
        /// <param name="count">闪烁窗口的次数</param>
        /// <param name="timeOut">窗口闪烁的频度，毫秒为单位；若该值为0，则为默认图标的闪烁频度</param>
        /// <param name="always">是否总是闪烁，不管窗口是否已经最大化</param>
        public static void FlashWin(IntPtr hwnd,int count,int timeOut,bool always = false)
        {
            FLASHWINFO fInfo = new FLASHWINFO();
            fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
            fInfo.hwnd = hwnd;

            if(always)
            {
                fInfo.dwFlags = FLASHW_ALL;
            }
            else
            {
                fInfo.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
            }
            fInfo.uCount = (uint)count;// UInt32.MaxValue;
            fInfo.dwTimeout = (uint)timeOut;
            FlashWindowEx(ref fInfo);

            //参考:http://t.zoukankan.com/onesmail-p-7227432.html
        }
        #endregion


        #region 开机自启动

        /// <summary>
        /// 设置/取消程序开机自启动
        /// </summary>
        /// <param name="started">是否启动</param>
        public static bool SetAutoStart(bool started)
        {
            bool isSetOk = false;

            //需要尝试两个注册表位置，因为有些系统用户可能权限不够
            List<RegistryKey> baseRegistryKeys = new List<RegistryKey> { Registry.LocalMachine,Registry.CurrentUser };

            foreach(RegistryKey baseRegistryKey in baseRegistryKeys)
            {
                RegistryKey runKey = null;
                try
                {
                    runKey = baseRegistryKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run",true);//打开注册表
                    if(runKey == null)
                        runKey = baseRegistryKey.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");//不存在时创建注册表

                    if(started)//设置自启动
                    {
                        runKey.SetValue(GlobalData.AppName_en,GlobalData.AppPath + " -autostart");
                    }
                    else//取消自启动
                    {
                        if(runKey.GetValue(GlobalData.AppName_en) != null)
                        {
                            runKey.DeleteValue(GlobalData.AppName_en,false);//取消自启动
                        }
                    }
                    isSetOk = true;

                    break;
                }
                catch(SecurityException)//权限不足
                {
                    continue;
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    runKey?.Close();
                }
            }

            return isSetOk;
        }


        /// <summary>
        /// 获取是否已设为开机启动
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static bool IsAutoStrat()
        {
            bool isAutoStrat = false;

            //需要尝试两个注册表位置，因为有些系统用户可能权限不够
            List<RegistryKey> baseRegistryKeys = new List<RegistryKey> { Registry.LocalMachine,Registry.CurrentUser };

            foreach(RegistryKey baseRegistryKey in baseRegistryKeys)
            {
                try
                {
                    using(RegistryKey runKey = baseRegistryKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run"))
                    {
                        if(runKey == null) continue;

                        object value = runKey.GetValue(GlobalData.AppName_en);//获取注册表值 
                        if(value != null)
                        {
                            if(value.ToString() == GlobalData.AppPath + " -autostart")
                            {
                                isAutoStrat = true;
                                break;
                            }
                        }
                    }
                }
                catch(Exception)
                {
                    continue;
                }
            }
            return isAutoStrat;
        }
        #endregion 开机自启动


        #region 键鼠空闲时间
        /// <summary>
        /// 获取键盘鼠标空闲时间，单位：秒
        /// </summary>
        /// <returns>键鼠空闲时间，单位秒</returns>
        public static long GetIdleTimeSeconds()
        {
            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = Marshal.SizeOf(lastInputInfo);
            if(!GetLastInputInfo(ref lastInputInfo)) return 0;
            return (Environment.TickCount - (long)lastInputInfo.dwTime) / 1000;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct LASTINPUTINFO
        {
            [MarshalAs(UnmanagedType.U4)]
            public int cbSize;
            [MarshalAs(UnmanagedType.U4)]
            public uint dwTime;
        }
        /// <summary>
        /// 调用windows API获取鼠标键盘空闲时间
        /// </summary>
        /// <param name="plii"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
        #endregion 键鼠空闲时间


        public static double CPUTotalUsage = 0;

        /// <summary>
        /// 获取所有核心的CPU的占用率的值
        /// </summary>
        /// <returns></returns>
        public static double GetCPUTotalUsage()
        {
            double total = 0;
            ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_Processor");
            foreach(ManagementObject myobject in searcher.Get().Cast<ManagementObject>())
            {
                total += myobject["LoadPercentage"].ToDouble();
            }
            CPUTotalUsage = total;
            return total;
        }


        /// <summary>
        /// 操作系统版本信息
        /// </summary>
        /// <returns></returns>
        public static string GetSystemOsName()
        {
            ManagementClass info = new ManagementClass("Win32_OperatingSystem");//系统信息
            foreach(ManagementObject o in info.GetInstances())
            {
                return o["Caption"].ToString();
            }

            return Environment.OSVersion.ToString();
        }


        #region 强制刷新 Windows 资源管理器

        // Windows API 常量和方法声明
        private const int SHCNE_ASSOCCHANGED = 0x08000000;
        private const int SHCNF_FLUSHNOWAIT = 0x2000;

        [DllImport("shell32.dll",CharSet = CharSet.Auto,SetLastError = true)]
        public static extern void SHChangeNotify(int wEventId,uint uFlags,IntPtr dwItem1,IntPtr dwItem2);

        /// <summary>
        /// 强制刷新 Windows 资源管理器，以便更新视图。
        /// </summary>
        public static void RefreshExplorer()
        {
            // 发送 SHCNE_ASSOCCHANGED 消息给资源管理器，以便刷新所有视图
            SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_FLUSHNOWAIT,IntPtr.Zero,IntPtr.Zero);
        }

        #endregion 强制刷新 Windows 资源管理器


        /// <summary>
        /// 获取当前进程的ID
        /// </summary>
        /// <returns></returns>
        public static int GetCurrentProcessId()
        {
            return Process.GetCurrentProcess().Id;
        }

        /// <summary>
        /// 根据进程ID获取进程名称
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        public static string GetProcessNameById(int pid)
        {
            return GetProcessById(pid).ProcessName;
        }

        /// <summary>
        /// 根据进程ID获取进程对象
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        public static Process GetProcessById(int pid)
        {
            return Process.GetProcessById(pid);
        }

        /// <summary>
        /// 根据进程ID结束进程
        /// </summary>
        /// <param name="pid"></param>
        public static void KillProcessById(int pid)
        {
            Process process = GetProcessById(pid);
            process.Kill();
            process.WaitForExit();
            process.Close();
        }


        #region 设置当前程序的dll搜索路径
        [DllImport("kernel32.dll",CharSet = CharSet.Auto,SetLastError = true)]
        public static extern bool SetDllDirectory(string lpPathName);

        /// <summary>
        /// 设置当前程序的dll搜索路径,（可以是任何位置）
        /// </summary>
        /// <param name="dllPath"></param>
        public static void SetAppDllDirectory(string dllPath)
        {
            SetDllDirectory(dllPath);
        }
        #endregion 设置当前程序的dll搜索路径
    }


}
